package com.ct;

import cn.hutool.core.lang.Console;
import cn.hutool.log.StaticLog;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@SpringBootTest
public class RedisDemo {
    @Autowired
    private StringRedisTemplate redisTemplate;  // Redis 操作类

//    @Resource
//    private RedisUtil<String> redisUtil;

    @Test
    public void a1() {
        HashMap<String, Object> valueMap = new HashMap<>();
        valueMap.put("aaa","AAA");
        valueMap.put("bbb","AAA");
        valueMap.put("ccc","AAA");
        Console.log("someMap->{}",valueMap.toString());
        redisTemplate.opsForValue().set("someMap", valueMap.toString());
        Console.log("aaaa");
    }

    @Test
    public void redisString() {
        //存储数据
        redisTemplate.opsForValue().set("name", "张三");

        String oldValue = redisTemplate.opsForValue().getAndSet("name", "李四");
        StaticLog.info("oldValue旧值:{}", oldValue);

        //获取数据
        String name = redisTemplate.opsForValue().get("name");
        StaticLog.info("name:{}", name);

        //删除数据
        //redisTemplate.delete("name");

        //设置过期时间  5 分钟后自动过期
        redisTemplate.opsForValue().set("code", "123456", 5, TimeUnit.MINUTES);

        //自增 / 自减
        redisTemplate.opsForValue().increment("count");  // 递增 1
        redisTemplate.opsForValue().increment("count", 5); // 递增 5
        redisTemplate.opsForValue().decrement("count");  // 递减 1
    }


    //Redis 的 List 是一个双向链表，可以作为队列（FIFO）或栈（LIFO）使用。
    @Test
    public void redisList() {
        //从左边插入（类似队列）
        redisTemplate.opsForList().leftPush("userList", "Alice");
        redisTemplate.opsForList().leftPush("userList", "Bob");

        //从右边插入
        redisTemplate.opsForList().rightPush("userList", "Charlie");

        //获取列表长度
        Long size = redisTemplate.opsForList().size("userList");

        //获取列表元素
        List<String> users = redisTemplate.opsForList().range("userList", 0, -1);
        System.out.println(users);

        //弹出元素
        String firstUser = redisTemplate.opsForList().leftPop("userList");  // 从左侧取出（队列）
        String lastUser = redisTemplate.opsForList().rightPop("userList");  // 从右侧取出（栈）

    }

    // 操作哈希(Hash)  Redis 的 Hash 结构可以存储类似 Map<String, Object> 的数据。
    @Test
    public void redisHash() {
        //存储数据
        redisTemplate.opsForHash().put("user:1001", "name", "张三");
        redisTemplate.opsForHash().put("user:1001", "age", "28");

        //获取单个字段
        String name = (String) redisTemplate.opsForHash().get("user:1001", "name");

        //获取所有字段
        Map<Object, Object> user = redisTemplate.opsForHash().entries("user:1001");
        System.out.println(user);

        //删除字段
        redisTemplate.opsForHash().delete("user:1001", "age");
    }

    //操作集合(Set)  Redis Set 是一个无序集合，适用于存储唯一值的场景，如标签、好友列表等。
    @Test
    public void redisSet() {
        //添加元素
        redisTemplate.opsForSet().add("tags", "Java", "Spring", "Redis");

        //获取所有元素
        Set<String> tags = redisTemplate.opsForSet().members("tags");

        //删除元素
        redisTemplate.opsForSet().remove("tags", "Java");
    }

    //操作有序集合（ZSet）  Redis ZSet 是一个有序集合，每个元素都有一个 score（分数），可用于排行榜等场景。
    @Test
    public void redisZSet() {
        //添加元素
        redisTemplate.opsForZSet().add("ranking", "Alice", 100);
        redisTemplate.opsForZSet().add("ranking", "Bob", 80);

        //获取排名
        Long rank = redisTemplate.opsForZSet().rank("ranking", "Alice"); // 排名（从0开始）
        StaticLog.info("rank:{}", rank);

        //获取范围
        Set<String> top3 = redisTemplate.opsForZSet().range("ranking", 0, 2); // 获取前三名
        StaticLog.info("top3:{}", top3);
    }

    @Test
    public void redisOther() {
        // 判断 Key 是否存在
        Boolean exists = redisTemplate.hasKey("name");

        //设置 Key 过期时间
        redisTemplate.expire("name", 10, TimeUnit.SECONDS);

        //获取 key 的剩余存活时间
        Long expireTime = redisTemplate.getExpire("user:1001", TimeUnit.SECONDS);
        System.out.println("剩余存活时间（秒）: " + expireTime);

        // 事务（开启事务执行多条命令）
        List<Object> results = redisTemplate.execute(new SessionCallback<List<Object>>() {
            @Override
            public List<Object> execute(RedisOperations operations) {
                operations.multi();  // 开启事务
                operations.opsForValue().set("testKey", "123");
                operations.opsForValue().increment("count", 2);
                return operations.exec(); // 提交事务
            }
        });

    }

    @Test
    public void redisMyself() {
        String key1="channel(交通联合):city(北京)";
        String key2="channel(交通联合):city(深圳)";
        String key3="channel(海南E出行):city(武汉)";
        String key4="channel(海南E出行):city(上海)";
        redisTemplate.opsForHash().increment(key1, "A", 1);
        redisTemplate.opsForHash().increment(key2, "A", 1);
        redisTemplate.opsForHash().increment(key3, "A", 1);
        redisTemplate.opsForHash().increment(key4, "A", 1);

        redisTemplate.opsForZSet().add("key1", "B", 80);
    }
}
